package com.webserver.http;

import com.sun.jmx.snmp.SnmpUnknownAccContrModelException;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求对象
 * 该类的每一个实例用于表示浏览器发送过来的一个请求内容
 * 每个请求由三部分构成：
 * 请求行，消息头，消息正文
 */
public class HttpRequest {
    //请求行相关信息
    private String method;//请求方式
    private String uri;//抽象路径
    private String protocol;//协议版本
    private String requestURI;//记录uri中的请求部分“？”左侧内容
    private String queryString;//记录uri中的参数部分，“？”右侧内容
    //保存表单提交的每一组参数，
    //key：参数名（输入框的名字）
    //value：参数值（输入框中用户输入的信息）
    private Map<String,String> parameters =new HashMap<>();
    //消息头相关信息
    //Key:消息头的名字  value：消息头对应的值
   private Map<String,String> headers =new HashMap<>();

   //消息正文相关信息

    private Socket socket;
    public HttpRequest(Socket socket) throws IOException, EmptyRequestException {
        this.socket=socket;
        //1.1：解析请求行
        parseRequestLine();
        //1.2：解析消息头
        parseHeaders();
        //1.3：解析消息正文
        parseContent();
    }
    private void parseRequestLine() throws IOException, EmptyRequestException {
        String line =readLine();
        if (line.isEmpty()){//如果请求行是空字符串则是空请求
            throw new EmptyRequestException();
        }
        System.out.println(line);
        //将请求行内容解析并复制给对应的method，uri，protocol上
        String[] data = line.split("\\s");
        method =data[0];
        uri =data[1];
        protocol =data[2];
        System.out.println("method:"+method);
        System.out.println("uri:"+uri);
        System.out.println("protocol:"+protocol);

        parseURI();//进一步解析uri
    }
    //进一步对uri进行解析
    private void parseURI(){
          /*
            uri有两种情况:含有参数和不含有参数的

            不含有参数(uri中没有"?")
            直接将uri赋值给requestURI即可

            若含有参数
            1:现将uri按照"?"拆分为请求部分和参数部分
              并将请求部分赋值给requestURI
              将参数部分赋值给queryString

            2:将参数部分进一步拆分
              将参数部分按照"&"拆分出每一组参数,之后每一组参数再
              按照"="拆分出参数名与参数值.将参数名作为key,参数值
              作为value保存到parameters这个Map中

         */
//        if (uri.contains("?")){
//            String[] data =uri.split("\\?");
//            requestURI =data[0];
//            queryString=data[1];
//            String[] data1=queryString.split("&");
//            for (int i=0;i<data1.length;i++){
//                 String[] a=data1[i].split("=");
//                 String key =a[0];
//                 String value=a[1];
//                parameters.put(key,value);
//            }
//        }else{
//            requestURI =uri;
//        }
        String[] arr =uri.split("\\?");
        requestURI=arr[0];
        if (arr.length>1){//有参数
            queryString=arr[1];
            //将参数按照&拆分
            String[] paras=queryString.split("&");
            for (String para : paras){
                //每组参数按照=拆分
                String[] data=para.split("=");
                if (data.length>1){
                    parameters.put(data[0],data[1]);
                }else {
                    parameters.put(data[0],null);
                }
            }
        }
        System.out.println("requestURI:"+requestURI);
        System.out.println("queryString:"+queryString);
        System.out.println("parameters:"+parameters);
    }
    private void parseHeaders() throws IOException {
        String line;
        String[] data;
        while (!(line =readLine()).isEmpty()){
            System.out.println("消息头："+line);
            data =line.split(":\\s");
            headers.put(data[0],data[1]);
        }
        System.out.println("headers:"+headers);
    }
    private void parseContent(){}

    private String readLine() throws IOException {
        /*
        调用同一个socket对象的getInputStream()或GetOutStream()
        方法若干次，返回的始终都是同一个流
         */
        InputStream in =socket.getInputStream();
        StringBuilder builder =new StringBuilder();
        int d ;
        char pre ='a',cur ='a';
        while ((d =in.read())!=-1){
            cur=(char)d;//本次读取到的字符
            if (pre==13 && cur==10 ){
                //是否联系读取到了回车+换行
                break;
            }
            builder.append(cur);
            pre =cur;
        }
        return builder.toString().trim();
    }

    public String getMethod() {
        return method;
    }

    public String getUri() {
        return uri;
    }

    public String getProtocol() {
        return protocol;
    }
    /**
     * 根据给定的消息头名字获取对应消息头的值
     * name
     */
    public String getHeader(String name){
        return headers.get(name);
    }

    public String getRequestURI() {
        return requestURI;
    }

    public String getQueryString() {
        return queryString;
    }
    public String getParameter(String name){
        return parameters.get(name);
    }
}
